/*
 *  Fragmentation.cpp
 *  GLRender
 *
 *  Created by Patrick zulian on 5/27/10.
 *  Copyright 2010 University  of Lugano. All rights reserved.
 *
 */

#include "Fragmentation.h"
#include "Configuration.h"
#include "WRenderer.h"

Fragmentation::Fragmentation(WObject * object)
: radius(object->getRadius()),  duration(350), theta(3.14), timeElapsed(0), center(object->position()), dir(object->velocity()), finished(false), mat(RGBd(0.5, 0.5, 0.5))
{
	numberOfFragments = radius*20;
	this->setDLname(((WRenderer *)Configuration::getInstance()->renderer)->FRAGMENT_DL);
	this->setMaterial(&mat);
	initFragments();
}


void 
Fragmentation::initFragments()
{
	dir.normalize();
	

	std::vector<Fragment>::iterator frag;
	

	for (int i = 0; i < numberOfFragments; i++)
		fragments.push_back(newFragment());
}

Fragmentation::~Fragmentation()
{
	
}

const Fragment 
Fragmentation::newFragment() const 
{
	Fragment frag;
	frag.radius = newRandom()/2.0;
	frag.position = center;
	frag.rotation = newRandomPoint();
	frag.velocity = (dir + newRandomPoint())*2.0;
	return frag;
}

const Point3d
Fragmentation::newRandomPoint() const
{
	Point3d p(newRandom(), newRandom(), newRandom());
	p.normalize();
	return p;
}

double
Fragmentation::newRandom() const
{
	return ((double) rand()) / ((double) RAND_MAX)*2-1.0;
}

void 
Fragmentation::step(const double tau)
{
	std::vector<Fragment>::iterator frag;
	for (frag = fragments.begin(); frag != fragments.end(); ++frag) {
		frag->position += tau * frag->velocity;
		frag->rotation *= tau * theta;
	}
	timeElapsed += tau;
	if (timeElapsed >= duration) {
		finished = true;
	}
}

void 
Fragmentation::renderOn(AbstractRenderer * renderer)
{
	
	glPushMatrix();
	//glTranslated(center.x(), center.y(), center.z());
	
	std::vector<Fragment>::iterator frag;
	for (frag = fragments.begin(); frag != fragments.end(); ++frag) {
		renderFragment(*frag, renderer);
	}
	glPopMatrix();
}

void
Fragmentation::renderFragment(Fragment &fragment, AbstractRenderer * renderer)
{
	glPushMatrix();
	glTranslated(fragment.position.x(), fragment.position.y(), fragment.position.z());
	glRotated(fragment.rotation.x(), 1, 0, 0);
	glRotated(fragment.rotation.y(), 0, 1, 0);
	glRotated(fragment.rotation.z(), 0, 0, 1);
	
	glScaled(fragment.radius, fragment.radius, fragment.radius);
	
	
	renderer->render(this);
	glPopMatrix();
}